[POJ1741]Tree

2020-03-15
POJ

题意

求树上路径长$\leq k$的路径条数,$n\leq 10^4$

题解

点分治,递归处理重心

用根为 $cur$ 的整棵树的答案减去以 $v$ 为根的每个子树中的答案就是合法的答案

处理过的重心打上vis隔开

调试记录

求子树重心的时候totsz最好传sz[v]>sz[u]?totsz-sz[u]?sz[v]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
const int maxn = 1e4 + 5;
const int INF = 0x3f3f3f3f;
using namespace std;
struct E{
int to, nxt, l;
}e[maxn << 1];
int head[maxn], tot = 0;
void addedge(int u, int v, int l){
e[++tot].to = v, e[tot].nxt = head[u], e[tot].l = l;
head[u] = tot;
}
bool vis[maxn];
int n, k, sz[maxn], dis[maxn], Max[maxn], rt;
void getRt(int cur, int fa, int totsz){
sz[cur] = 1; Max[cur] = -1;
for (int i = head[cur]; i; i = e[i].nxt){
int v = e[i].to;
if (v == fa || vis[v]) continue;
getRt(v, cur, totsz);
sz[cur] += sz[v];
Max[cur] = max(Max[cur], sz[v]);
} Max[cur] = max(Max[cur], totsz - sz[cur]);
if (Max[cur] < Max[rt]) rt = cur;
}
vector <int> v;
void getDis(int cur, int fa){
v.push_back(dis[cur]);
for (int i = head[cur]; i; i = e[i].nxt){
int v = e[i].to;
if (v == fa || vis[v]) continue;
dis[v] = dis[cur] + e[i].l;
getDis(v, cur);
}
}
int calc(int u, int fa, int d){
dis[u] = d; v.clear(); getDis(u, fa);
sort(v.begin(), v.end());
vector <int>::iterator l = v.begin(), r = v.end() - 1;
int res = 0;
while (l != r){
if (*r + *l <= k) res += r - l, ++l;
else --r;
} return res;
}
int ans;
void dfs(int cur, int totsz){
vis[cur] = 1;
ans += calc(cur, 0, 0);
for (int i = head[cur]; i; i = e[i].nxt){
int v = e[i].to;
if (vis[v]) continue;
ans -= calc(v, cur, e[i].l);
rt = 0; int ssz = sz[v] > sz[cur] ? totsz - sz[cur] : sz[v];
getRt(v, cur, ssz);
dfs(rt, ssz);
}
}
int main(){
scanf("%d%d", &n, &k);
while (n != 0){
ans = 0; memset(vis, 0, sizeof vis);
memset(head, 0, sizeof head); tot = 0;
for (int u, v, l, i = 1; i < n; i++){
scanf("%d%d%d", &u, &v, &l);
addedge(u, v, l); addedge(v, u, l);
}
Max[0] = INF; getRt(1, rt = 0, n);
dfs(rt, n); printf("%d\n", ans);
scanf("%d%d", &n, &k);
}
return 0;
}